﻿// Project: Salient
// http://salient.codeplex.com
// 
// Copyright 2010, Sky Sanders <sky at skysanders.net>
// Dual licensed under the MIT or GPL Version 2 licenses.
// http://salient.codeplex.com/license
// 
// Date: April 24 2010 

#region

using System;
using System.Net;
using Salient.Net;

#endregion
//
namespace Salient.Web.Hosting
{
    ///<summary>
    ///</summary>
    ///<typeparam name="T"></typeparam>
    public abstract class ServerFixtureBase<T> where T : IWebServer, new()
    {
        /// <summary>
        /// 
        /// </summary>
        protected readonly IWebServer Server = new T();
        /// <summary>
        /// 
        /// </summary>
        protected abstract string AppPath { get; }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void StartServer()
        {
            Server.StartServer(AppPath);
        }

        /// <summary>
        /// Will start specified application as "localhost" on loopback and first available port in the range 8000-10000 with vpath "/"
        /// </summary>
        /// <param name="applicationPath">Physical path to application.</param>
        protected void StartServer(string applicationPath)
        {
            StartServer(applicationPath, null, 0, null, null);
        }

        /// <summary>
        /// Will start specified application on loopback
        /// </summary>
        /// <param name="applicationPath">Physical path to application.</param>
        /// <param name="port">Port to listen on.</param>
        /// <param name="virtualPath">Optional. defaults to "/"</param>
        /// <param name="hostName">Optional. Is used to construct RootUrl. Defaults to "localhost"</param>
        protected void StartServer(string applicationPath, int port, string virtualPath, string hostName)
        {
            StartServer(applicationPath, null, port, virtualPath, hostName);
        }


        /// <summary>
        /// </summary>
        /// <param name="applicationPath">Physical path to application.</param>
        /// <param name="ipAddress">IP to listen on.</param>
        /// <param name="port">Port to listen on.</param>
        /// <param name="virtualPath">Optional. default value '/'</param>
        /// <param name="hostName">Optional. Used to construct RootUrl. Defaults to 'localhost'</param>
        protected void StartServer(string applicationPath, IPAddress ipAddress, int port, string virtualPath,
                                   string hostName)
        {
            hostName = string.IsNullOrEmpty(hostName) ? "localhost" : hostName;
            virtualPath = string.IsNullOrEmpty(virtualPath) ? "/" : virtualPath;
            ipAddress = ipAddress ?? IPAddress.Loopback;
            port = port == 0 ? NetworkUtils.GetAvailablePort(8000, 9000, ipAddress, false) : port;
            if (!NetworkUtils.IsPortAvailable(ipAddress, port))
            {
                throw new ArgumentException(string.Format("Port {0} is already in use.", port), "port");
            }
            Server.StartServer(applicationPath, ipAddress, port, virtualPath, hostName);
        }


        ///<summary>
        ///</summary>
        public virtual void TestFixtureSetUp()
        {
            StartServer();
        }

        ///<summary>
        ///</summary>
        public virtual void StopServer()
        {
            Server.StopServer();
        }


        ///<summary>
        ///</summary>
        public virtual void TestFixtureTearDown()
        {
            StopServer();
        }

        /// <summary>
        /// Combine the RootUrl of the running web application with the relative url
        /// specified.
        /// </summary>
        /// <param name="relativeUrl"></param>
        /// <returns></returns>
        public virtual string NormalizeUrl(string relativeUrl)
        {
            return NetworkUtils.NormalizeUrl(Server.RootUrl, relativeUrl);
        }
    }
}